package com.homelock.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import com.homelock.common.sequence.SnowflakeFactory;
import com.homelock.constants.DevUserRoleEnum;
import com.homelock.entity.HlDevInfo;
import com.homelock.entity.HlDevUser;
import com.homelock.entity.HlDevUserExample;
import com.homelock.mapper.HlDevUserMapper;
import com.homelock.service.check.LockUserCheckUtil;
import com.homelock.vo.DevUserVo;
import com.pi.base.enumerate.record.RecordState;
import com.pi.base.exception.ServiceException;
import com.pi.base.util.bean.ObjectTool;
import com.pi.base.util.time.DateTools;
import com.pi.uc.dao.entity.UcUserEntity;
import com.pi.uc.service.UcUserService;

@Service
public class LockUserService {

    @SuppressWarnings("unused")
    private static final Logger logger = LoggerFactory.getLogger(LockUserService.class);

    private HlDevUserMapper devUserMapper;

    private HlDevInfoService devInfoService;

    private UcUserService userService;
    
    private HlDevUserUnlockService devUserUnlockService;

    @Autowired
    public LockUserService(
            HlDevUserMapper devUserMapper, 
            HlDevInfoService devInfoService, 
            UcUserService userService,
            HlDevUserUnlockService devUserUnlockService) {
        Assert.notNull(devUserMapper, "锁具用户数据服务为空");
        Assert.notNull(devInfoService, "锁具服务为空");
        Assert.notNull(userService, "用户服务为空");
        Assert.notNull(devUserUnlockService, "用户解锁服务为空");
        this.devUserMapper = devUserMapper;
        this.devInfoService = devInfoService;
        this.userService = userService;
        this.devUserUnlockService = devUserUnlockService;
    }

    public Long addLockUser(Long devId, String lockUserName, Boolean admin,String mobile) {
        return addLockUser(devId, lockUserName, admin, null,mobile);
    }

    public Long addLockUser(Long devId, String lockUserName, Boolean admin, Long bindUserId,String mobile){
        int roleType =( null == admin || !admin) ? DevUserRoleEnum.USER.getRole() : DevUserRoleEnum.ADMIN.getRole();
        return addLockUser(devId, lockUserName, roleType, null,mobile);
    }

    public Long addLockUser(Long devId, String lockUserName, int roleType, Long bindUserId,String mobile) {
        LockUserCheckUtil.checkLockUserAdd(devId, lockUserName,mobile);
        //校验门锁是否存在
        HlDevInfo devInfo = devInfoService.getDevInfobyIdIfExist(devId);
        if(null == devInfo) {
            throw new ServiceException("门锁未注册");
        }
        // 校验手机号是否在该锁具下注册过
        HlDevUser mobileUser = queryInfoByMobileAndDevIdAndState(devId,mobile,RecordState.STATE_NORMAL.getState());
        if(mobileUser != null){
            logger.error("该锁[{}]下已经存在该手机[{}]用户[{}:{}]",devId,mobile,mobileUser.getId(),mobileUser.getDevUserName());
            throw new ServiceException("该锁下已存在该手机号的用户");
        }
        HlDevUser record = new HlDevUser();
       // record.setDevUserRole( (byte) ((null == admin || !admin) ? DevUserRoleEnum.OWNER.getRole() : DevUserRoleEnum.ADMIN.getRole()));
        record.setDevUserRole((byte)roleType);
        record.setCreateDate(new Date());
        record.setUpdateDate(record.getCreateDate());
        record.setDevUserName(lockUserName);
        record.setDevId(Long.valueOf(devId));
        if (null != bindUserId && bindUserId.longValue() >= 0L) {
            record.setUserId(bindUserId);
        }else if(StringUtils.isNotBlank(mobile)) {
            UcUserEntity ucUserInfo = userService.queryUserInfoByPhone(mobile, devInfo.getSourceId());
            if(null != ucUserInfo) {
                record.setUserId(ucUserInfo.getId());
            }
        }
        record.setId(SnowflakeFactory.getDefaultWorker().nextId());
        record.setMobile(mobile);
        record.setState(RecordState.STATE_NORMAL.getState());
        devUserMapper.insertSelective(record);
        return record.getId();
    }

    @Transactional(rollbackFor= Exception.class)
    public void removeLockUser(Long devId, Long lockUserId) {
        LockUserCheckUtil.checkLockUserDel(devId, lockUserId);
        HlDevUser lockUserInfo = getLockUserInfo(devId, lockUserId);
        devUserMapper.deleteByPrimaryKey(lockUserInfo.getId());
        //移除用户解锁方式
        devUserUnlockService.clearByDevId(devId);
        
    }

    public void updateLockUser(Long devId, Long userId, String devUserName) {
        LockUserCheckUtil.checkLockUserNameUpdate(devId, userId, devUserName);
        HlDevUser lockUserInfo = getLockUserInfo(devId, userId);
        HlDevUser updated = new HlDevUser();
        updated.setId(lockUserInfo.getId());
        updated.setDevUserName(devUserName);
        devUserMapper.updateByPrimaryKeySelective(updated);
    }

    public void switchLockUserAdmin(Long devId, Long userId, Boolean adminFlag) {
        LockUserCheckUtil.checkSwitchLockUserAdmin(devId, userId, adminFlag);
        HlDevUser lockUserInfo = getLockUserInfo(devId, userId);
        // 查询是否为门锁注册人，不能关闭
        HlDevInfo devInfo = devInfoService.getDevInfobyId(devId);
        if (null == devInfo || devInfo.getOwnerId().longValue() == lockUserInfo.getUserId()) {
            throw new ServiceException("用户是门锁的注册人，不能修改设置权限");
        }
        HlDevUser updated = new HlDevUser();
        updated.setId(lockUserInfo.getId());
        updated.setDevUserRole((byte) ((null == adminFlag || !adminFlag) ? DevUserRoleEnum.USER.getRole()
                : DevUserRoleEnum.ADMIN.getRole()));
        devUserMapper.updateByPrimaryKeySelective(updated);
    }

    public HlDevUser getLockUserInfo(Long devId, Long userId) {
        LockUserCheckUtil.checkLockUserQuery(devId, userId);
        HlDevUserExample example = new HlDevUserExample();
        example.createCriteria().andIdEqualTo(userId).andDevIdEqualTo(devId);
        List<HlDevUser> devUserist = devUserMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(devUserist)) {
            throw new ServiceException("LOCK_USER_NOT_EXIST");
        }
        return devUserist.get(0);
    }

    public List<DevUserVo> queryLockUserList(Long devId) {
        LockUserCheckUtil.checkLockUserListQuery(devId);
        HlDevInfo devInfo = devInfoService.getDevInfobyId(devId);
        userService.queryUserInfo(devInfo.getOwnerId());
        HlDevUserExample example = new HlDevUserExample();
        example.createCriteria().andDevIdEqualTo(devId).andStateEqualTo(RecordState.STATE_NORMAL.getState());
        List<HlDevUser> devUserist = devUserMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(devUserist)) {
            return new ArrayList<>(0);
        }
        List<DevUserVo> devUserVoList = new ArrayList<>(devUserist.size());
        for (HlDevUser devUser : devUserist) {
            DevUserVo devUserVo = new DevUserVo();
            devUserVo.setMobile(devUser.getMobile());
            devUserVo.setAdminFlag(DevUserRoleEnum.isAdmin(devUser.getDevUserRole().intValue()) ? 1 : 0);
            devUserVo.setLockUserId(devUser.getId().toString());
            devUserVo.setLockUserName(devUser.getDevUserName());
            devUserVo.setOpTime(DateTools.getFullDate(devUser.getCreateDate()));
            devUserVo.setLockUserRole(devUser.getDevUserRole().intValue());
            // 基于老数据的问题（之前注册人没有放入role 而是将注册人的权限设置成admin 不知是故意的设计还是其他原因），这边需要重新check下
            if(devUser.getDevUserRole().intValue() == DevUserRoleEnum.ADMIN.getRole()){
                if (devInfo.getOwnerId().longValue() == devUser.getUserId()) {
                    devUserVo.setLockUserRole(DevUserRoleEnum.OWNER.getRole());
                }
            }
            devUserVoList.add(devUserVo);
        }
        return devUserVoList;
  }
 

    public List<HlDevUser> queryUserLockList(Long userId) {
        LockUserCheckUtil.checkUserLockListQuery(userId);
        HlDevUserExample example = new HlDevUserExample();
        example.createCriteria().andUserIdEqualTo(userId).andStateEqualTo(RecordState.STATE_NORMAL.getState());
        example.setOrderByClause("id DESC");
        return devUserMapper.selectByExample(example);
    }

    public HlDevUser queryLockUserByAppUserId(Long devId, Long appUserId) {
        LockUserCheckUtil.checkLockUserQueryByAppId(devId, appUserId);
        return queryLockUserByDevIdAndUserId(devId,appUserId);
    }

    public HlDevUser queryLockUserByDevIdAndUserId(Long devId,Long userId){
        HlDevUserExample example = new HlDevUserExample();
        example.createCriteria().andDevIdEqualTo(devId)
                .andUserIdEqualTo(userId).andStateEqualTo(RecordState.STATE_NORMAL.getState());
        return ObjectTool.getOne(devUserMapper.selectByExample(example));

    }

    public List<HlDevUser> queryLockUserListByIds(Long devId, List<Long> lockUserIds) {
        if (CollectionUtils.isEmpty(lockUserIds)) {
            return new ArrayList<>(0);
        }
        HlDevUserExample example = new HlDevUserExample();
        example.createCriteria().andDevIdEqualTo(devId).andIdIn(lockUserIds)
                .andStateEqualTo(RecordState.STATE_NORMAL.getState());
        return devUserMapper.selectByExample(example);
    }

    public void clearByDevId(Long devId) {
        HlDevUserExample example = new HlDevUserExample();
        example.createCriteria().andDevIdEqualTo(devId).andStateEqualTo(RecordState.STATE_NORMAL.getState());
        HlDevUser devUser = new HlDevUser();
        devUser.setState(RecordState.STATE_DELETE.getState());
        devUserMapper.updateByExampleSelective(devUser, example);
    }

    public List<HlDevUser> queryAnyLockUserByDevId(Long devId){
        HlDevUserExample example = new HlDevUserExample();
        example.createCriteria().andDevIdEqualTo(devId).andStateEqualTo(RecordState.STATE_NORMAL.getState());
        return devUserMapper.selectByExample(example);
    }

    public HlDevUser queryInfoByMobileAndDevIdAndState(Long devId,String mobile,boolean state){
        HlDevUserExample example = new HlDevUserExample();
        example.createCriteria().andDevIdEqualTo(devId).andMobileEqualTo(mobile).andStateEqualTo(state);
        List<HlDevUser> list = devUserMapper.selectByExample(example);
        if(CollectionUtils.isEmpty(list)){
            return null;
        }
        return list.get(0);
    }

    /**
     * 查询某个锁具下某个角色的全部信息
     * @param devId
     * @param roleCode
     * @return
     */
    public List<HlDevUser> queryUsersByDevIdAndRole(Long devId,int roleCode){
        HlDevUserExample example = new HlDevUserExample();
        example.createCriteria().andDevIdEqualTo(devId).andDevUserRoleEqualTo((byte)roleCode).andStateEqualTo(RecordState.STATE_NORMAL.getState());
        return devUserMapper.selectByExample(example);
    }

    public HlDevUser queryByIdAndDevId(Long id,Long devId){
        HlDevUserExample example = new HlDevUserExample();
        example.createCriteria().andIdEqualTo(id).andDevIdEqualTo(devId).andStateEqualTo(RecordState.STATE_NORMAL.getState());
        List<HlDevUser> list = devUserMapper.selectByExample(example);
        if(CollectionUtils.isEmpty(list)){
            return null;
        }
        return list.get(0);
    }
    
    public List<HlDevUser> queryWaitBindedLock(String mobile){
        HlDevUserExample example = new HlDevUserExample();
        example.createCriteria()
        .andMobileEqualTo(mobile)
        .andStateEqualTo(RecordState.STATE_NORMAL.getState()).andUserIdEqualTo(0L);
        List<HlDevUser> list = devUserMapper.selectByExample(example);
        return list;
    }

    public void bindUserLock(List<Long> waitBindedLockUserIdList, Long userId) {
        HlDevUserExample example = new HlDevUserExample();
        example.createCriteria()
        .andStateEqualTo(RecordState.STATE_NORMAL.getState()).andIdIn(waitBindedLockUserIdList);
        List<HlDevUser> list = devUserMapper.selectByExample(example);
        if(CollectionUtils.isEmpty(list)) {
            return;
        }
        List<HlDevUser> collect = list.stream().filter(o -> o.getUserId() == 0L).collect(Collectors.toList());
        if(CollectionUtils.isEmpty(collect)) {
            return;
        }
        List<Long> userIdCollect = collect.stream().map(HlDevUser::getId).collect(Collectors.toList());
        example.clear();
        example.createCriteria().andIdIn(userIdCollect);
        HlDevUser updated = new HlDevUser();
        updated.setUserId(userId);
        devUserMapper.updateByExampleSelective(updated, example);
    }
}
